package com.yungu.swift.assets.driver.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.yungu.swift.assets.driver.dao.DriverMessageMapper;
import com.yungu.swift.assets.driver.model.dto.DriverDto;
import com.yungu.swift.assets.driver.model.dto.DriverMessageDto;
import com.yungu.swift.assets.driver.model.param.AdminDriverMessageParam;
import com.yungu.swift.assets.driver.service.DriverMessageService;
import com.yungu.swift.assets.driver.service.DriverService;
import com.yungu.swift.assets.driver.thread.DriverMessageThread;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.mapper.IMapper;
import com.yungu.swift.base.model.api.ApiPageParam;
import com.yungu.swift.base.service.impl.BaseServiceImpl;
import com.yungu.swift.common.model.dto.CommonMessageStatusDto;
import com.yungu.swift.common.service.CommonMessageStatusService;
import com.yungu.swift.constants.DriverConstant;
import com.yungu.swift.constants.MagicConstant;
import com.yungu.swift.socket.push.service.PushService;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.ParamUtil;
import com.yungu.swift.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * CommonDriverMessageServiceImpl
 **/

@Service
public class DriverMessageServiceImpl extends BaseServiceImpl<DriverMessageDto> implements DriverMessageService {
    @Autowired
    private DriverMessageMapper driverMessageMapper;
    @Reference
    private CommonMessageStatusService commonMessageStatusService;
    @Reference
    private PushService pushService;
    @Reference
    private DriverService driverService;

    private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2,
            new NamedThreadFactory("commonDriverMessage"));

    @Override
    protected IMapper<DriverMessageDto> getMapper() {
        return driverMessageMapper;
    }


    @Override
    public ResponseData<Boolean> recall(String uuid) {
        DriverMessageDto dto = new DriverMessageDto();
        dto.setUuid(uuid);
        dto.setStatus(CommonMessageStatusDto.STATUS_RECALL);
        if (driverMessageMapper.edit(dto) > 0) {
            return ResponseData.buildSuccessResponse("消息撤回成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "消息撤回失败", Boolean.FALSE);
    }


    @Override
    public ResponseData<Boolean> saveAndSend(AdminDriverMessageParam driverMessageParam) {
        DriverMessageDto messageDto = new DriverMessageDto();
        BeanUtils.copyProperties(driverMessageParam, messageDto);
        messageDto.setUuid(StringUtils.buildUUID());
        //默认已发送状态
        messageDto.setStatus(CommonMessageStatusDto.STATUS_SEND);
        messageDto.setType(CommonMessageStatusDto.TYPE_SYSTEM);
        messageDto.setCreateOn(new Date());
        messageDto.setCreateBy(driverMessageParam.getUserUuid());
        messageDto.setAppid(driverMessageParam.getAppid());
        messageDto.setCompanyUuid(ParamUtil.defaultIfNull(driverMessageParam.getCompanyUuid(), ""));
        messageDto.setAgentUuid(ParamUtil.defaultIfNull(driverMessageParam.getAgentUuid(), ""));
        messageDto.setSendTime(new Date());
        // 发送类型是链接
        if (driverMessageParam.getSendType() == 2) {
            messageDto.setLinkUrl(buildLinkUrl(messageDto.getLinkUrl(), messageDto.getSendType()));
        }
        List<String> targetUuids = new ArrayList<>();
        // 全部发送
        if (messageDto.getSendObject() == 1) {
            messageDto.setTargetName("全部");
            Map<String, Object> map = MapUtils.convertObjToMap(driverMessageParam);
            map.put("status", DriverConstant.DRIVER_STATUS_NORMAL);
            map.put("type", messageDto.getBusinessType());
            targetUuids = driverService.getDriverUuidList(map).getData();
        }
        // 部分发送
        if (messageDto.getSendObject() == 2) {
            targetUuids.addAll(org.springframework.util.StringUtils.commaDelimitedListToSet(messageDto.getTargetUuid()));
            List<DriverDto> driverDtos = driverService.list(MapUtils.build("driverMobileList", targetUuids)).getData();
            if (CollectionUtils.isNotEmpty(driverDtos)) {
                messageDto.setTargetName(driverDtos.stream().map(DriverDto::getName).collect(Collectors.joining(",")));
                targetUuids.clear();
                for (DriverDto driverDto : driverDtos) {
                    targetUuids.add(driverDto.getUuid());
                }
            }
        }
        if (driverMessageMapper.add(messageDto) > 0) {
            //添加中间表，推送
            DriverMessageThread runnable = new DriverMessageThread(pushService, commonMessageStatusService, messageDto, targetUuids);
            executorService.execute(runnable);
            return ResponseData.buildSuccessResponse("消息新增成功", Boolean.TRUE);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "消息新增失败", Boolean.FALSE);
    }

    private String buildLinkUrl(String linkUrl, Integer sendType) {
        if (StringUtils.isNotEmpty(linkUrl) && MagicConstant.INT_TWO == sendType && !linkUrl.contains(MagicConstant.SYMBOL_DOUBLE_DIAGONAL)) {
            return "http://" + linkUrl;
        }
        return linkUrl;
    }


    /**
     * 新增消息，实时推送
     *
     * @param dto
     * @return
     * @author Zerrion
     */
    @Override
    public ResponseData<Boolean> add(DriverMessageDto dto) {
        //默认已发送状态
        dto.setStatus(CommonMessageStatusDto.STATUS_SEND);
        return super.add(dto);
    }

    @Override
    public ResponseData<List<DriverMessageDto>> queryDriMsgList(Map<String, Object> params, ApiPageParam pageParam) {
        PageBounds pageBounds = new PageBounds(pageParam.getNowPage(), pageParam.getPageSize());
        return ResponseData.buildSuccessResponse(driverMessageMapper.queryDriMsg(params, pageBounds));
    }


    private static class NamedThreadFactory implements ThreadFactory {
        protected static final AtomicInteger poolNumber = new AtomicInteger(1);

        protected final AtomicInteger threadNumber = new AtomicInteger(1);
        protected final ThreadGroup group;
        protected final String namePrefix;
        protected final boolean isDaemon;


        public NamedThreadFactory(String name) {
            this(name, true);
        }

        public NamedThreadFactory(String preffix, boolean daemon) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            namePrefix = preffix + "-" + poolNumber.getAndIncrement() + "-thread-";
            isDaemon = daemon;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            // Default value is parent thread's
            t.setContextClassLoader(NamedThreadFactory.class.getClassLoader());
            t.setDaemon(isDaemon);
            return t;
        }

    }
}